<template>
    <div>
        <ElCard class="marginBottom">
            <ElForm inline>
                <ElFormItem label="角色名称" style="margin-bottom: 0;">
                    <ElInput v-model="searchRoleName" placeholder="请输入角色名称" maxlength="10" show-word-limit></ElInput>
                </ElFormItem>
                <ElFormItem style="margin-bottom: 0;">
                    <ElButton @click="onSearchRole" type="primary">搜索</ElButton>
                    <ElButton @click="onReset" type="primary">重置</ElButton>
                </ElFormItem>
            </ElForm>
        </ElCard>
        <ElCard>
            <template #header>
                <ElButton type="primary" @click="onAddRole" v-hasPermi="['sys:role:insert']">新增角色</ElButton>
            </template>
            <ElTable :data="resultData.records" v-loading="isLoading">
                <ElTableColumn label="序号" type="index" width="100px" align="center"></ElTableColumn>
                <ElTableColumn label="角色名称" prop="name"></ElTableColumn>
                <ElTableColumn label="所属部门">
                    <template #="{ row, $index }: { row: SysRoleVO, $index: number }">
                        {{ row.deptId ? sysDeptIdToName[row.deptId] : row.deptId }}
                    </template>
                </ElTableColumn>
                <ElTableColumn label="角色类型">
                    <template #="{ row, $index }: { row: SysRoleVO, $index: number }">
                        {{ appStore.dict?.['sys_role_type']?.[row.type] ?? row.type }}
                    </template>
                </ElTableColumn>
                <ElTableColumn label="备注" prop="comment"></ElTableColumn>
                <ElTableColumn label="创建时间" prop="createTime"></ElTableColumn>
                <ElTableColumn label="更新时间" prop="updateTime"></ElTableColumn>
                <ElTableColumn label="操作" width="350px">
                    <template #="{ row, $index }: { row: SysRoleVO, $index: number }">
                        <ElButton v-if="row.type != ROLE_TYPE_SUPER_ADMIN" type="warning" @click="onEditRole(row)"
                            v-hasPermi="['sys:role:update']">编辑
                        </ElButton>
                        <ElButton v-if="row.type != ROLE_TYPE_SUPER_ADMIN" type="warning"
                            @click="onEditRoleDataPermission(row)" v-hasPermi="['sys:role:update']">数据权限
                        </ElButton>
                        <Popconfirm :title="`确定删除${row.name}?`" icon="Delete" @confirm="onDeleteRole(row)">
                            <ElButton v-if="row.type != ROLE_TYPE_SUPER_ADMIN" type="danger"
                                v-hasPermi="['sys:role:delete']">删除</ElButton>
                        </Popconfirm>
                    </template>
                </ElTableColumn>
            </ElTable>
            <template #footer>
                <Pagination v-model="resultData" @pageInfoChange="handleQuery"></Pagination>
            </template>
        </ElCard>

        <!-- 角色 新增/编辑 对话框 -->
        <ElDialog v-model="dialogInfo.show" :title="dialogInfo.title" width="700px" :show-close="false"
            :close-on-press-escape="false" :close-on-click-modal="false">
            <ElForm ref="formInstance" :rules="checkFormRoles" :model="formInfo" label-width="auto">
                <ElFormItem label="所属部门" prop="deptId">
                    <DeptSelect v-model="formInfo.deptId"></DeptSelect>
                </ElFormItem>
                <ElFormItem label="角色类型" prop="type">
                    <ElRadioGroup v-model="formInfo.type">
                        <ElRadio value="ADMIN">管理员</ElRadio>
                        <ElRadio value="USER">普通角色</ElRadio>
                    </ElRadioGroup>
                </ElFormItem>
                <ElFormItem label="角色名称" prop="name">
                    <ElInput v-model="formInfo.name" placeholder="请输入角色名称" maxlength="10" show-word-limit></ElInput>
                </ElFormItem>
                <ElFormItem label="菜单权限">
                    <MenuSelect v-if="dialogInfo.show" v-model="formInfo.menuIds" :all-value="false" />
                </ElFormItem>
            </ElForm>
            <template #footer>
                <ElButton @click="hideDialog">取消</ElButton>
                <ElButton type="primary" @click="submitFormData()">确定</ElButton>
            </template>
        </ElDialog>

        <!-- 角色 分配数据权限 对话框相关内容 -->
        <ElDialog v-model="dataPermDialogInfo.show" :title="dataPermDialogInfo.title" width="700px" :show-close="false"
            :close-on-press-escape="false" :close-on-click-modal="false">
            <ElForm ref="dataPermFormInstance" :model="dataPermFormInfo" label-width="auto">
                <ElFormItem label="权限范围">
                    <ElSelect v-model="dataPermFormInfo.dataPermissionType">
                        <ElOption v-for="item in deptSupportDataPermission" :key="item"
                            :label="appStore.dict?.['data_permission_type']?.[item]" :value="item" />
                    </ElSelect>
                </ElFormItem>
                <ElFormItem label="数据权限" v-show="dataPermFormInfo.dataPermissionType === 'CUSTOM'">
                    <ElCheckbox v-model="deptExpand" @change="handleCheckedTreeExpand($event)">展开/折叠
                    </ElCheckbox>
                    <ElCheckbox v-model="deptSelectAll" @change="handleCheckedTreeNodeAll($event)">全选/全不选
                    </ElCheckbox>
                    <ElCheckbox v-if="false" v-model="deptCheckStrictly" @change="handleCheckedTreeConnect($event)">父子联动
                    </ElCheckbox>
                </ElFormItem>
                <ElFormItem label=" " v-show="dataPermFormInfo.dataPermissionType === 'CUSTOM'">
                    <ElTree class="lineBorder" :data="sysDeptData" show-checkbox default-expand-all
                        ref="deptTreeInstance" node-key="id" :check-strictly="!deptCheckStrictly" empty-text="加载中，请稍候"
                        :props="{ label: 'name', children: 'children' }" />
                </ElFormItem>
            </ElForm>
            <template #footer>
                <ElButton @click="hideDataPermDialog">取消</ElButton>
                <ElButton type="primary" @click="submitDataPermissionFormData()">确定</ElButton>
            </template>
        </ElDialog>
    </div>
</template>

<script setup lang="ts">
import { addRole, deleteRole, queryRole, queryRoleDataPerm, queryRolePage, queryRoleSupportDataPerm, updateRole, updateRoleDataPerm } from '@/api/sysRole/sysRole';
import { type SysRoleDataPermissionDTO, type SysRoleDTO, type SysRoleFiltDTO, type SysRoleVO } from '@/api/sysRole/sysRoleType';
import Pagination from '@/components/custom/Pagination.vue';
import Popconfirm from '@/components/custom/Popconfirm.vue';
import { useFormDialog } from '@/hook/useDialog';
import { usePageQuery } from '@/hook/useQuery';
import { ElButton, ElCard, ElCheckbox, ElDialog, ElForm, ElFormItem, ElInput, ElOption, ElRadio, ElRadioGroup, ElSelect, ElTable, ElTableColumn, ElTree, type FormRules } from 'element-plus';
import { nextTick, onBeforeMount, reactive, ref } from 'vue';
import DeptSelect from '../components/DeptSelect.vue';
import { queryDeptAll } from '@/api/sysDept/sysDept';
import MenuSelect from '../components/MenuSelect.vue';
import { ROLE_TYPE_SUPER_ADMIN } from '@/common';
import useAppStore from '@/stores/useAppStore';
import type { SysDeptVO } from '@/api/sysDept/sysDeptType';

const appStore = useAppStore()

/**
 * 搜索筛选角色名
 */
const searchRoleName = ref<string>()

/**
 * 所有部门信息的id与name映射
 */
let sysDeptIdToName: Record<string, string>

/**
 * 分配数据权限Dialog 支持的权限范围
 */
const deptSupportDataPermission = ref<string[]>([])
/**
 * 分配数据权限Dialog 部门树 展开/折叠
 */
const deptExpand = ref(true)
/**
 * 分配数据权限Dialog 部门树 全选/全不选
 */
const deptSelectAll = ref(false)
/**
 * 分配数据权限Dialog 部门树 父子联动
 */
const deptCheckStrictly = ref(true)
/**
 * 分配数据权限Dialog 部门树 组件对象
 */
const deptTreeInstance = ref()
/**
 * 部门树数据
 */
const sysDeptData = ref<SysDeptVO[]>([])

/**
 * 新增角色
 */
const onAddRole = () => {
    showDialog('新增角色', undefined, () => addRole(formInfo.value))
}

/**
 * 修改角色
 * @param sysRoleVO 要修改的角色
 */
const onEditRole = (sysRoleVO: SysRoleVO) => {
    showDialog('编辑角色', queryRole({ id: sysRoleVO.id }), () => updateRole({ id: sysRoleVO.id }, formInfo.value))
}

/**
 * 分配角色数据权限
 * @param sysRoleVO 要修改的角色
 */
const onEditRoleDataPermission = async (sysRoleVO: SysRoleVO) => {
    deptSupportDataPermission.value = await queryRoleSupportDataPerm()
    sysDeptData.value = await queryDeptAll()
    const sysRoleDataPermissionVO = await queryRoleDataPerm({ id: sysRoleVO.id })
    showDataPermDialog(`分配数据权限-${sysRoleVO.name}`, sysRoleDataPermissionVO, () => updateRoleDataPerm({ id: sysRoleVO.id }, dataPermFormInfo.value))
    if (sysRoleDataPermissionVO.dataPermissionType === 'CUSTOM' && sysRoleDataPermissionVO.deptIds) {
        nextTick(() => {
            deptTreeInstance.value.setCheckedKeys(sysRoleDataPermissionVO.deptIds)
        })
    }
}

/**
 * 删除角色
 * @param sysRoleVO 要删除的角色
 */
const onDeleteRole = async (sysRoleVO: SysRoleVO) => {
    await deleteRole({ id: sysRoleVO.id })
    handleQuery()
}

/**
 * 封装查询方法
 */
const {
    handleQuery, // 封装后的查询方法
    handleParamChange,
    resultData, // 查询到的数据
    isLoading   // 是否正在查询
} = usePageQuery<SysRoleFiltDTO, SysRoleVO>(queryRolePage)

/**
 * 根据角色名搜索
 */
const onSearchRole = () => {
    handleParamChange({
        name: searchRoleName.value
    })
    handleQuery()
}

/**
 * 重置搜索条件
 */
const onReset = () => {
    searchRoleName.value = undefined
    onSearchRole()
}

/**
 * 角色 新增/编辑 对话框相关内容
 */
const {
    showDialog,
    hideDialog,
    submitFormData,
    dialogInfo,
    formInfo,
    formInstance
} = useFormDialog<SysRoleDTO>(() => handleQuery())

/**
 * 角色 分配数据权限 对话框相关内容
 */
const {
    showDialog: showDataPermDialog,
    hideDialog: hideDataPermDialog,
    submitFormData: submitDataPermFormData,
    dialogInfo: dataPermDialogInfo,
    formInfo: dataPermFormInfo,
    formInstance: dataPermFormInstance
} = useFormDialog<SysRoleDataPermissionDTO>(() => handleQuery())

/**
 * 提交分配权限结果
 */
const submitDataPermissionFormData = () => {
    // 被选中的部门节点
    let checkedKeys = deptTreeInstance.value.getCheckedKeys()
    // 半选中的部门节点
    // let halfCheckedKeys = deptTreeInstance.value.getHalfCheckedKeys()
    // checkedKeys.unshift(...halfCheckedKeys)
    // 如果数据权限类型为自定义，则将选中的部门信息填入待提交数据中
    if (dataPermFormInfo.value.dataPermissionType === 'CUSTOM') {
        dataPermFormInfo.value.deptIds = checkedKeys
    }
    submitDataPermFormData()
}

/**
 * 树权限（展开/折叠）
 * @param value 
 */
const handleCheckedTreeExpand = (value: any) => {
    for (let i = 0; i < sysDeptData.value.length; i++) {
        deptTreeInstance.value.store.nodesMap[sysDeptData.value[i].id ?? 0].expanded = value
    }
}
/**
 * 树权限（全选/全不选）
 * @param value 
 */
const handleCheckedTreeNodeAll = (value: any) => {
    deptTreeInstance.value.setCheckedNodes(value ? sysDeptData.value : [])
}
/**
 * 树权限（父子联动）
 * @param value 
 */
const handleCheckedTreeConnect = (value: any) => {
    deptCheckStrictly.value = value
}

/**
 * 对话框校验规则
 */
const checkFormRoles = reactive<FormRules<SysRoleDTO>>({
    name: [
        { required: true, message: '请输入角色名称', trigger: 'blur' },
        { min: 2, max: 10, message: '角色名称长度为2 - 10', trigger: 'blur' }
    ],
    deptId: [
        { required: true, message: '请选择部门', trigger: 'blur' },
    ],
    type: [
        { required: true, message: '请选择角色类型', trigger: 'blur' },
    ]
})

/**
 * 挂载前加载部门信息
 */
onBeforeMount(async () => {
    const sysDeptVOArrayOfList = await queryDeptAll(true)
    sysDeptIdToName = sysDeptVOArrayOfList.reduce((sysDeptIdToName, current) => {
        if (current.id) {
            sysDeptIdToName[current.id] = current.name;
        }
        return sysDeptIdToName;
    }, {} as Record<string, string>);
})
</script>

<style scoped lang="scss"></style>